home *** CD-ROM | disk | FTP | other *** search
- TITLE Hercules graphics module
-
- ; Michael Gordon - 8-Dec-86
- ;
- ; Certain routines were taken from the Hercules BIOS of Dave Tutelman - 8/86
- ; Others came from pcgraph.asm included in GNUPLOT by Colin Kelley
- ;
- ; modified slightly by Colin Kelley - 22-Dec-86
- ; added header.mac, parameterized declarations
- ; added dgroup: in HVmodem to reach HCh_Parms and HGr_Parms - 30-Jan-87
- ; modified by Russell Lang 3 Jun 1988
- ; added H_init
-
- include header.mac
-
- if1
- include lineproc.mac
- endif
-
-
- GPg1_Base equ 0B800h ; Graphics page 1 base address
-
- _text segment
-
- public _H_line, _H_color, _H_mask, _HVmode, _H_puts
- public _H_init
-
- HCfg_Switch equ 03BFH ; Configuration Switch - software switch
- ; to select graphics card memory map
-
- beginproc _H_init
- mov al, 03H ; allow graphics in b8000:bffff
- mov dx, HCfg_Switch
- out dx, al
- ret
- _H_init endp
-
- hpixel proc near
- ror word ptr bmask,1
- jc cont
- ret
- cont:
- push ax
- push bx
- push cx
- push dx
- push si
- mov cx,ax ; x
- mov dx,bx ; y
- ;
- ; [couldn't this be done faster with a lookup table? -cdk]
- ;
- ; first compute the address of byte to be modified
- ; = 90*[row/4] + [col/8] + 2^D*[row/4] + 2^F*page
- mov bh,cl ; col (low order) in BH
- mov bl,dl ; row (low order) in BL
- and bx,0703H ; mask the col & row remainders
- IFDEF iAPX286
- shr cx,3 ; col / 8
- shr dx,2 ; row / 4
- mov al,90
- mul dx ; AX = 90*[ row/4 ]
- add ax,cx ; ... + col/8
- shl bl,5 ; align row remainder
- ELSE ; same as above, obscure but fast for 8086
- shr cx,1 ; divide col by 8
- shr cx,1
- shr cx,1
- shr dx,1 ; divide row by 4
- shr dx,1
- shl dx,1 ; begin fast multiply by 90 (1011010 B)
- mov ax,dx
- shl dx,1
- shl dx,1
- add ax,dx
- shl dx,1
- add ax,dx
- shl dx,1
- shl dx,1
- add ax,dx ; end fast multiply by 90
- add ax,cx ; add on the col/8
- shl bl,1 ; align row remainder
- shl bl,1
- shl bl,1
- shl bl,1
- shl bl,1
- ENDIF
- add ah,bl ; use aligned row remainder
- end_adr_calc: ; address of byte is now in AX
- mov dx,GPg1_Base ; base of pixel display to DX
- mov es,dx ; ...and thence to segment reg
- mov si,ax ; address of byte w/ pixel to index reg
- mov cl,bh ; bit addr in byte
- mov al,80H ; '1000 0000' in AL
- shr al,cl ; shift mask to line up with bit to read/write
- set_pix: ; set the pixel
- or es:[si],al ; or the mask with the right byte
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- hpixel endp
-
- lineproc _H_line, hpixel
-
- ;
- ; clear - clear page 1 of the screen buffer to zero (effectively, blank
- ; the screen)
- ;
- clear proc near
- push es
- push ax
- push cx
- push di
- mov ax, GPg1_Base
- mov es, ax
- xor di, di
- mov cx, 4000h
- xor ax, ax
- cld
- rep stosw ; zero out screen page
- pop di
- pop cx
- pop ax
- pop es
- ret
- clear endp
-
- beginproc _H_color
- push bp
- mov bp,sp
- mov al,[bp+X] ; color
- mov byte ptr color,al
- pop bp
- ret
- _H_color endp
-
- beginproc _H_mask
- push bp
- mov bp,sp
- mov ax,[bp+X] ; mask
- mov word ptr bmask,ax
- pop bp
- ret
- _H_mask endp
-
- HCtrl_Port equ 03B8H ; Hercules 6845 control port IO addr
- HIndx_Port equ 03B4H ; Hercules 6845 index port IO addr
- HScrn_Enable equ 008h ; Control port bit to enable video
- HCh_Mode equ 020h ; Character output mode
- HGr_Mode equ 082h ; Graphics output mode page 1
-
- parm_count equ 12
-
- beginproc _HVmode
- push bp
- mov bp, sp
- push si
- mov ax, [bp+X]
- or ah, al
- mov al, HCh_Mode ; Assume character mode is wanted
- mov si, offset dgroup:HCh_Parms
- cmp ah, 0 ; nonzero means switch to graphics
- jz vmode_ok
- call near ptr clear ; clear the graphics page
- mov al, HGr_Mode
- mov si, offset dgroup:HGr_Parms
- vmode_ok:
- mov dx, HCtrl_Port
- out dx, al ; Set Hercules board to proper mode
- call near ptr setParms ; Set the 6845 parameters
- or al, HScrn_Enable ; Enable the video output
- out dx, al
- pop si
- pop bp
- ret
- _HVmode endp
-
- setParms proc near ; Send 6845 parms to Hercules board
- push ax
- push dx
- push si
- mov dx, HIndx_Port ; Index port addr -> DX
- mov ah, 0 ; 0 -> parameter counter
- sp_loop:
- mov al, ah
- out dx, al ; output to 6845 addr register
- inc dx ; next output to data register
- mov al, [si] ; next control byte -> al
- inc si
- out dx, al ; output control byte
- dec dx ; 6845 index addr -> dx
- inc ah ; bump addr
- cmp ah, parm_count
- jnz sp_loop
- pop si
- pop dx
- pop ax
- ret
- setParms endp
-
- ; H_puts - print text in graphics mode
- ;
- ; cx = row
- ; bx = column
- ; si = address of string (null terminated) to print
-
- beginproc _H_puts
- push bp
- mov bp, sp
- push si
- push ds
- mov si, [bp+X] ; string offset
-
- ifdef LARGE_DATA
- mov ds, [bp+X+2] ; string segment
- mov cx, [bp+X+4] ; row
- mov bx, [bp+X+6] ; col
- else
- mov cx, [bp+X+2] ; row
- mov bx, [bp+X+4] ; col
- endif
-
- ploop: lodsb ; get next char
- or al, al ; end of display?
- je pdone
- call near ptr display
- inc bx ; bump to next column
- jmp ploop
- pdone: pop ds
- pop si
- pop bp
- ret
- _H_puts endp
-
- ;
- ; display - output an 8x8 character from the IBM ROM to the Herc board
- ;
- ; AX = char, BX = column (0-89), CX = row(0-42) ** all preserved **
- ;
- CON8 db 8
- CON180 db 180
- IBMROM equ 0F000h
- CHARTAB equ 0FA6Eh
-
- display proc near
- push ds ; save the lot
- push es
- push ax
- push bx
- push cx
- push dx
- push si
- push di
-
- ; setup ds -> IBM ROM, and si -> index into IBM ROM character table located
- ; at 0fa6eh in the ROM
-
- and ax, 07fh
- mul cs:CON8 ; mult by 8 bytes of table per char
- mov si, ax
- mov ax, IBMROM
- mov ds, ax
- assume ds:nothing
- add si, CHARTAB ; add offset of character table
-
- ; compute index into Hercules screen memory for scan line 0. The remaining
- ; seven scan lines are all at fixed offsets from the first.
- ;
- ; Since graphics mode treats the screen as sets of 16x4 "characters",
- ; we need to map an 8x8 real character onto the front or back of
- ; a pair of graphics "characters". The first four scan lines of our
- ; 8x8 character will map to the top graphics "character", and the second
- ; four scan lines map to the graphics character on the "line" (4 scan
- ; lines high) below it.
- ;
- ; For some exotic hardware reason (probably speed), all scan line 0
- ; bits (i.e. every fourth scan line) are stored in memory locations
- ; 0-2000h in the screen buffer. All scan line 1 bits are stored
- ; 2000h-4000h. Within these banks, they are stored by rows. The first
- ; scan line on the screen (scan line 0 of graphics character row 0)
- ; is the first 45 words of memory in the screen buffer. The next 45
- ; words are the first scan line graphics row 1, and since graphics
- ; "characters" are 4 bits high, this second scan line is physically
- ; the fifth scan line displayed on the screen.
- ;
- ; SO, to display an 8x8 character, the 1st and 5th rows of dots are
- ; both scan line 0 of the graphics "character", the 2nd and 6th are
- ; scan line 1, and so on.
- ;
- ; The column (0-89) tells which byte in a scan line we need to load.
- ; Since it takes two rows of graphics characters to hold one row of
- ; our characters, column+90 is a index to scan line 4 rows of pixels
- ; higher (n+4). Thus 180 bytes of screen memory in any bank (0h, 2000h,
- ; 4000h, 6000h) represent a row of 8x8 characters.
- ;
- ; The starting location in screen memory for the first scan line of
- ; a character to be displayed will be: (row*180)+column
- ; The 5th scan line will be at: (row*180)+column+90
- ;
- ; The second and 6th scan lines will be at the above offsets plus
- ; the bank offset of 2000h. The third and 7th, add 4000h and finally
- ; the 4th and 8th, add 6000h.
- ;
- mov ax, GPg1_Base
- mov es, ax ; es = hercules page 0
- mov ax, cx ; get row
- mul cs:CON180 ; mult by 180(10)
- mov di, ax ; di = index reg
- cld ; insure right direction
-
- ;output 8 segments of character to video ram
-
- lodsb ; line 0
- mov es:[di+bx], al
- lodsb
- mov es:[di+bx+2000h], al ; line 1
- lodsb
- mov es:[di+bx+4000h], al ; line 2
- lodsb
- mov es:[di+bx+6000h], al ; line 3
- lodsb
- mov es:[di+bx+90], al ; line 4
- lodsb
- mov es:[di+bx+2000h+90], al ; line 5
- lodsb
- mov es:[di+bx+4000h+90], al ; line 6
- lodsb
- mov es:[di+bx+6000h+90], al ; line 7
-
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- pop es
- pop ds
- ret
- display endp
-
- _text ends
-
- _data segment
- bmask dw -1
- color db 1
- _data ends
-
- const segment
- HCh_Parms db 61H, 50H, 52H, 0FH, 19H, 06H, 19H, 19H, 02H, 0DH, 0BH, 0CH
- HGr_Parms db 35H, 2DH, 2EH, 07H, 5BH, 02H, 57H, 57H, 02H, 03H, 00H, 00H
- const ends
-
- end
-
-